using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

namespace BlockOS.Client
{
    public class Crosshair : MonoBehaviour
    {
        public Image cross, hit, progress, north, compass;
        [Space]
        public float commonAngle;
        public float blockedAngle;
        [Space]
        public AnimationCurve crossChangeCurve;
        public float crossChangeTime;
        [Space]
        public AnimationCurve northFadeCurve;
        public float northPadding;
        public float minNorthScale;
        public float maxNorthScale;

        public enum CrossStatus
        {
            Normal, NormalToBlocked, Blocked, BlockedToNormal
        }
        private CrossStatus crossStatus;
        // 0 - Normal, 1 - Blocked
        private float crossAnimTimer = 0;

        private bool hitPlaying = false;
        private float northRadius;

        private bool IsCompassActive
        {
            get => north.isActiveAndEnabled && compass.isActiveAndEnabled;
            set
            {
                north.gameObject.SetActive(value);
                compass.gameObject.SetActive(value);
            }
        }

        private void Start()
        {
            northRadius = 0.5f * (GetComponent<RectTransform>().sizeDelta.y + north.rectTransform.sizeDelta.y) + northPadding;
        }

        private void Update()
        {
            if (crossStatus == CrossStatus.NormalToBlocked)
            {
                if (crossAnimTimer >= crossChangeTime)
                {
                    SetCrossDataBlocked();

                    crossAnimTimer = crossChangeTime;
                    crossStatus = CrossStatus.Blocked;
                }

                UpdateAnimationData();

                crossAnimTimer += Time.deltaTime;
            }
            else if (crossStatus == CrossStatus.BlockedToNormal)
            {
                if (crossAnimTimer <= 0.0f)
                {
                    SetCrossDataNormal();

                    crossAnimTimer = 0.0f;
                    crossStatus = CrossStatus.Normal;
                }

                UpdateAnimationData();

                crossAnimTimer -= Time.deltaTime;
            }
        }

        #region Progress
        public void SetProgress(float normalizedProgress)
        {
            progress.material.SetFloat("_Angle", Mathf.Clamp01(normalizedProgress) * 360.0f);
        }
        #endregion

        #region Hit
        public void Hit()
        {
            if (hitPlaying) return;
            hitPlaying = true;
            StartCoroutine(PlayHitAnim(0.1f));
        }

        private IEnumerator PlayHitAnim(float time)
        {
            hit.gameObject.SetActive(true);
            yield return new WaitForSeconds(time);
            hit.gameObject.SetActive(false);
            hitPlaying = false;
        }
        #endregion

        #region Cross
        public void SetCrossBlocked()
        {
            if (crossStatus == CrossStatus.NormalToBlocked || crossStatus == CrossStatus.Blocked) return;
            crossStatus = CrossStatus.NormalToBlocked;
        }

        public void SetCrossNormal()
        {
            if (crossStatus == CrossStatus.BlockedToNormal || crossStatus == CrossStatus.Normal) return;
            crossStatus = CrossStatus.BlockedToNormal;
        }
        
        private void SetCrossDataBlocked()
        {
            cross.rectTransform.rotation = Quaternion.Euler(0, 0, blockedAngle);
        }

        private void SetCrossDataNormal()
        {
            cross.rectTransform.rotation = Quaternion.Euler(0, 0, commonAngle);
        }

        private void UpdateAnimationData()
        {
            cross.color = Color.Lerp(Color.white, Color.red, crossChangeCurve.Evaluate(crossAnimTimer / crossChangeTime));
            cross.rectTransform.rotation = Quaternion.Euler(0, 0, Mathf.Lerp(commonAngle, blockedAngle, crossChangeCurve.Evaluate(crossAnimTimer / crossChangeTime)));
        }
        #endregion

        #region Compass
        public void SetForward(Vector3 forward)
        {
            if (!IsCompassActive) return;

            var nf = new Vector2(forward.x, forward.z).normalized;

            north.rectTransform.anchoredPosition = new Vector2(-nf.x * northRadius, nf.y * northRadius);
        }

        public void SetForward3D(Vector3 forward)
        {
            if (!IsCompassActive) return;

            var nf = forward.normalized;

            var scaleFactor = Mathf.Lerp(minNorthScale, maxNorthScale, 0.5f * (1.0f - nf.z));
            var alpha = northFadeCurve.Evaluate(1.0f - Mathf.Abs(nf.z));

            north.rectTransform.anchoredPosition = new Vector2(-nf.x * northRadius, -nf.y * northRadius);
            north.transform.localScale = new Vector3(scaleFactor, scaleFactor, 1.0f);
            north.color = new Color(north.color.r, north.color.g, north.color.b, alpha);
        }

        public void ShowCompass()
        {
            IsCompassActive = true;
        }

        public void HideCompass()
        {
            IsCompassActive = false;
        }

        public void SwitchCompass()
        {
            IsCompassActive = !IsCompassActive;
        }
        #endregion
    }
}
